<template>
  <section class="standard-table-con h100" :style="{ height: height }">
    <div class="header-con">
      <slot name="table-header" />
    </div>
    <div class="fixed-con h100">
      <section class="left-side-con">
        <slot name="table-side" />
      </section>
      <section class="table-con h100 flex-column">
        <select-box
          v-show="showCheckedBoxCom"
          :select-num="nowSelectedKeys.length"
          @cancel-select="cancelSelect"
        ></select-box>
        <a-table
          :key="renderUpdateKey"
          v-model:selectedKeys="nowSelectedKeys"
          class="h100 flex-1"
          :style="{ height: showCheckedBoxCom ? 'calc(100% - 60px)' : null }"
          :columns="renderColumns"
          :data="showData"
          :loading="loading"
          :row-selection="tableRowSelection"
          :row-key="rowKey"
          :pagination="pagination"
          :row-class="rowClass"
          sticky-header
          :span-method="spanMethod"
          :bordered="bordered ? { wrapper: true, cell: true } : ''"
          span-all
          :scroll="scroll"
          @selection-change="selectionChange"
          @page-change="pageChange"
          @page-size-change="pageSizeChange"
          @row-click="rowClick"
        >
          <template #empty>
            <div class="table-empty">
              <tableEmpty />
              <div v-if="!props.empty" class="empty-description">暂无数据</div>
              <div v-else class="empty-description">{{ props.empty }}</div>
            </div>
          </template>
          <template #index="{ rowIndex }">
            <span> {{ startNumber + rowIndex + 1 }} </span>
          </template>
          <template
            v-for="item in renderCustomize"
            :key="item.dataIndex"
            #[item.slotName]="{ rowIndex }"
          >
            <component
              :is="item.component"
              v-if="item.componentName"
              :row-index="rowIndex"
              :record="data[rowIndex]"
              :render-key="item.dataIndex"
              v-bind="item.componentProps"
            />
            <slot
              v-else
              :name="item.slotName"
              :row-index="rowIndex"
              :record="data[rowIndex]"
            ></slot>
          </template>
          <template #operate="{ rowIndex }">
            <collapseBtn class="collapse-btn" :data-key="collapseBtnKey">
              <slot
                name="operate"
                :row-index="rowIndex"
                :record="data[rowIndex]"
              />
            </collapseBtn>
          </template>
        </a-table>
      </section>
    </div>
  </section>
</template>

<script setup lang="ts">
  import {
    ref,
    defineProps,
    PropType,
    defineAsyncComponent,
    shallowRef,
    watch,
    computed,
  } from 'vue';
  import lodash from 'lodash';
  import {
    ComponentCfg,
    createDefaultComponents,
    createDefaultConfig,
  } from '@/common/components/standard-table/config';
  import usePagination from '@/common/hooks/pagination';
  import selectBox from '@/common/components/standard-table/selectBox.vue';
  import tableEmpty from '@/common/components/image/tableEmpty.svg?component';

  // eslint-disable-next-line import/extensions
  import collapseBtn from '@/common/components/collapse-btn/collapse-btn.jsx';

  type RowSelectionType = 'checkbox' | 'radio' | '';

  const DEFAULT_COLUMNS_CONFIG = {
    ellipsis: true,
    tooltip: true,
    width: 100,
  };

  const props = defineProps({
    componentConfig: {
      type: Object,
      default: () => ({}),
    },
    renderConfig: {
      type: Object,
      default: () => ({}),
    },
    renderKeys: {
      type: Array as PropType<string[]>,
      default: () => [],
    },
    loading: {
      type: Boolean,
      default: false,
    },
    data: {
      type: Array,
      default: () => [],
    },
    total: {
      type: Number,
      default: 0,
    },
    selectedKeys: {
      type: Array,
      default: () => [],
    },
    rowKey: {
      type: String,
      default: 'id',
    },
    rowClass: {
      type: Function,
      default: () => {},
    },
    rowSelectionType: {
      type: String as PropType<RowSelectionType>,
      default: '',
    },
    columns: {
      type: Array,
      default: () => [],
    },
    collapseBtnKey: {
      type: String,
      default: '[0].children',
    },
    height: {
      type: String || null,
      default: null,
    },
    spanMethod: {
      type: Function,
      default: () => {},
    },
    bordered: {
      type: Boolean,
      default: false,
    },
    scroll: {
      type: Object,
      default: () => {
        return {
          x: 100,
        };
      },
    },
    empty: {
      type: String,
      default: '',
    },
    showCheckedBox: {
      type: Boolean,
      default: true,
    },
  });
  const { pagination, setCurrent, setPageSize, setTotal, queryPagination } =
    usePagination();
  const emit = defineEmits([
    'initColumnsEnd',
    'update:selectedKeys',
    'selectionChange',
    'pageSizeChange',
    'pageChange',
    'rowClickdata',
  ]);
  // 触发强制渲染
  const renderUpdateKey = ref(1);
  const showData = ref<any>([]);
  const tableRowSelection = ref();
  const nowSelectedKeys = ref(props.selectedKeys);
  const renderColumns = ref<any[]>([]); // 最终渲染的列
  const renderCustomize = ref<any[]>([]); // 自定义列
  const componentCfg: ComponentCfg = {
    // 所有组件
    ...createDefaultComponents(),
    ...props.componentConfig,
  };
  const allConfig: any = {
    ...createDefaultConfig(),
    ...props.renderConfig,
  };
  const initTableRowSelection = () => {
    const arr = ['checkbox', 'radio'];
    const cfg = {
      width: 50,
      fixed: true,
      showCheckedAll: true,
      onlyCurrent: true,
    };
    if (arr.includes(props.rowSelectionType)) {
      tableRowSelection.value = {
        ...cfg,
        type: props.rowSelectionType,
      };
    }
  };

  watch(
    () => props.selectedKeys,
    () => {
      console.log('发送了改变');
      nowSelectedKeys.value = props.selectedKeys;
    }
  );
  watch(
    () => props.total,
    () => {
      setTotal(props.total);
    }
  );
  watch(
    () => props.columns,
    () => {
      renderColumns.value = props.columns;
      renderUpdateKey.value += 1;
    }
  );
  watch(
    () => props.renderKeys,
    () => {
      initRender();
    }
  );
  watch(
    () => props.data,
    () => {
      const result = lodash.cloneDeep(props.data);
      result.forEach((item: any) => {
        Object.keys(item).forEach((key: any) => {
          if (item[key] === null) {
            item[key] = '-';
          }
        });
      });
      showData.value = result;
    },
    {
      deep: true,
    }
  );
  const startNumber = computed(() => {
    return queryPagination.value.pageSize * (queryPagination.value.pageNo - 1);
  });

  const initRender = () => {
    const renderList: any[] = [];
    const customizeComp: any[] = [];
    const defaultColumns = ['operate', 'index', 'secretLevel'];
    props.renderKeys.forEach((key: string) => {
      const targetCfg: any = allConfig[key];
      const pushTarget: any = {};

      if (targetCfg) {
        Object.assign(pushTarget, DEFAULT_COLUMNS_CONFIG, targetCfg);
      }

      if (targetCfg && componentCfg[targetCfg.componentName]) {
        Object.assign(pushTarget, {
          slotName: targetCfg.dataIndex,
          component: shallowRef(
            defineAsyncComponent(componentCfg[targetCfg.componentName])
          ),
        });
      }
      if (
        targetCfg &&
        targetCfg.slotName &&
        !defaultColumns.includes(targetCfg.slotName)
      ) {
        Object.assign(pushTarget, {
          slotName: targetCfg.slotName,
          component: targetCfg.slotName,
        });
      }

      if (pushTarget && pushTarget.title) {
        renderList.push(pushTarget);
      }
      if (pushTarget && pushTarget.component) {
        customizeComp.push(pushTarget);
      }
    });

    renderColumns.value = renderList;
    renderCustomize.value = customizeComp;
    emit('initColumnsEnd', renderList);
  };

  initRender();
  initTableRowSelection();
  setTotal(props.total);

  const selectionChange = (val: string[]) => {
    emit('update:selectedKeys', val);
    emit('selectionChange', val);
  };
  const pageChange = (val: number) => {
    setCurrent(val);
    emit('pageChange', lodash.cloneDeep(queryPagination.value));
  };
  const pageSizeChange = (val: number) => {
    setPageSize(val);
    emit('pageSizeChange', lodash.cloneDeep(queryPagination.value));
  };
  const rowClick = (val: any) => {
    emit('rowClickdata', val);
  };
  const cancelSelect = () => {
    nowSelectedKeys.value = [];
    selectionChange([]);
  };
  const showCheckedBoxCom = computed(() => {
    if (!props.showCheckedBox) {
      return false;
    }
    if (props.rowSelectionType !== 'checkbox') {
      return false;
    }
    if (nowSelectedKeys.value && nowSelectedKeys.value.length) {
      return true;
    }
    return false;
  });

  const getStatus = () => {
    return {
      ...queryPagination.value,
    };
  };

  defineExpose({ getStatus, setCurrent });
</script>

<style lang="less" scoped>
  @import url('../common.less');
  .standard-table-con {
    background: #fff;
    border-radius: 8px;
    :deep(.arco-table-pagination) {
      margin-top: 0px;
      padding-top: 16px;
      background-color: #fff !important;
    }
  }

  .fixed-con {
    display: flex;
    flex-direction: row;
    width: 100%;
  }

  .header-con {
    width: 100%;
  }

  .table-con {
    flex: 1;
    width: 1px;
  }

  .collapse-btn {
    // ::v-deep(.arco-space-item) {
    //   margin-right: 5px !important;
    // }
    ::v-deep(.arco-btn-size-medium) {
      padding: 0;
      height: 14px;
    }
  }
  ::v-deep(.arco-table .arco-spin) {
    justify-content: space-between;
  }
  .table-empty {
    box-sizing: border-box;
    width: 100%;
    padding: 10px 0;
    text-align: center;
  }
  .empty-description {
    color: rgb(var(--gray-5));
    font-size: 14px;
  }
</style>
